package com.example.gprcdemo;

import android.content.Context;
import android.util.Log;

import com.example.gprcdemo.helloworld.GreeterGrpc;
import com.example.gprcdemo.helloworld.Reply;
import com.example.gprcdemo.helloworld.OtherRequest;
import com.google.protobuf.ByteString;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

/**
 * @Author : ZYB
 * @Date : on 2023/12/12 .
 * @Description :
 */
public class GRPCClient {

    private final String TAG = GRPCClient.class.toString();

    private final String host = "localhost";
    private final int port = 9005;
    private Context context;

    private ManagedChannel managedChannel;
    private GreeterGrpc.GreeterStub stub;

    // 在构造函数中连接
    public GRPCClient(Context context) {
        this.context = context;
        managedChannel = ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build();
            stub = GreeterGrpc.newStub(managedChannel);
    }

    // 使用广播的方法发送数据更新ui
    private void sendInfo(String info) {
        /*Intent intent = new Intent("main.info");
        intent.putExtra("info", info);
        context.sendBroadcast(intent);*/
        Log.d(TAG, info);

    }

    // 简单一元模式 异步
    public void simpleHello() {
        // 构建简单的消息发送
        OtherRequest request = OtherRequest.newBuilder().setReqInfo("simpleHello").build();
        stub.simpleHello(request, new StreamObserver<Reply>() {
            @Override
            public void onNext(Reply value) {
                Log.d(TAG, "simpleHello onNext.");
                String info = "[服务端->客户端]" + value.getRepInfo();
                sendInfo(info);
            }

            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "simpleHello onError.");
            }

            @Override
            public void onCompleted() {
                Log.d(TAG, "simpleHello onCompleted.");
            }
        });
    }

    // 客户端流模式 异步
    public void clientStream() {
        StreamObserver<OtherRequest> requestStreamObserver = stub.clientStream(new StreamObserver<Reply>() {
            @Override
            public void onNext(Reply value) {
                Log.d(TAG, "clientStream onNext.");
                String info = "[服务端->客户端]" + value.getRepInfo();
                sendInfo(info);
            }

            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "clientStream onError.");
            }

            @Override
            public void onCompleted() {
                Log.d(TAG, "clientStream onCompleted.");
            }
        });
        requestStreamObserver.onNext(OtherRequest.newBuilder().setReqInfo("clientStream1").build());
        requestStreamObserver.onNext(OtherRequest.newBuilder().setReqInfo("clientStream2").build());
        requestStreamObserver.onCompleted();
    }

    // 服务端流模式 和客户端流模式正好相反，本质都是差不多的, 客户端发送一个数据包告诉服务端，我需要某某数据，然后服务器将对应的所有信息都发送给客户端。
    public void serverStream() {
        OtherRequest request = OtherRequest.newBuilder().setReqInfo("serverStream").build();
        stub.serverStream(request, new StreamObserver<Reply>() {
            @Override
            public void onNext(Reply value) {
                Log.d(TAG, "serverStream onNext.");
                String info = "[服务端->客户端]" + value.getRepInfo();
                sendInfo(info);
            }

            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "serverStream onError.");
            }

            @Override
            public void onCompleted() {
                Log.d(TAG, "serverStream onCompleted.");
            }
        });
    }

    // 双向流模式
    public void bothFlowStream() {
        StreamObserver<OtherRequest> streamObserver = stub.bothFlowStream(new StreamObserver<Reply>() {
            @Override
            public void onNext(Reply value) {
                Log.d(TAG, "bothFlowStream onNext.");
                String info = "[服务端->客户端]" + value.getRepInfo();
                sendInfo(info);
            }

            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "bothFlowStream onError.");
            }

            @Override
            public void onCompleted() {
                Log.d(TAG, "bothFlowStream onCompleted.");
            }
        });
        streamObserver.onNext(OtherRequest.newBuilder().setReqInfo("bothFlowStream1").build());
        streamObserver.onNext(OtherRequest.newBuilder().setReqInfo("bothFlowStream2").build());
        streamObserver.onCompleted();
    }

    //与普通请求相比，就在第一步建立通道有所不同，需要设置CA证书，其他步骤都相同。
    /*public static ManagedChannel newSSLChannel(String host, int port, String authority, InputStream... certificates) {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(certificates);
        return OkHttpChannelBuilder.forAddress(host, port)
                //overrideAuthority非常重要，必须设置调用
                .overrideAuthority(authority)
                .sslSocketFactory(sslParams.sSLSocketFactory)
                .build();
    }*/
    public void dowolandFile(String fileName){

        OtherRequest request = OtherRequest.newBuilder().setReqInfo(fileName).build();
        stub.serverDownloadFile(request, new StreamObserver<Reply>() {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();

            @Override
            public void onNext(Reply value) {
                ByteString content = value.getContent();
                byte[] fileBytes = content.toByteArray();
                Log.i(TAG, "onNext长度: "+value.getLoadProgress());
                try {
                    buffer.write(fileBytes);
                    if (value.getLoadProgress()==value.getAllSize()){
                        FileSaver.saveFile(context,buffer.toByteArray(),"/storage/emulated/0/DCIM/"+request.getReqInfo()+".jpg",null);
                    }
                } catch (IOException e) {
                    cloneBuffer();
                }
                // 将字节数组保存到本地文件
            }

            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "serverStream onError."+t.getCause());
                cloneBuffer();
            }

            @Override
            public void onCompleted() {
                // 下载完成后的处理逻辑
                Log.d(TAG, "File download completed");
                cloneBuffer();
            }
            void  cloneBuffer(){
                try {
                    if (buffer!=null) {
                        buffer.close();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
}